 /*
* Copyright(C) 2010,Hikvision Digital Technology Co., Ltd 
* 
* File   consoleMain.cpp
* Discription
* Version    1.0
* Author     panyadong
* Create Date2010_3_25
* Modification History
*/

#ifndef __APPLE__

#include <ros/ros.h>
#include <ros/package.h>
#include <stdio.h>
#include <iostream>
#include "GetStream.h"
#include "public.h"
#include "ConfigParams.h"
#include "Alarm.h"
#include "CapPicture.h"
#include "playback.h"
#include "Voice.h"
#include "tool.h"
#include <string.h>

#include <signal.h>
#include "maindecte_msgs/Msgdata.h"
#include "maindecte_srvs/maindecte.h"
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/xfeatures2d.hpp"
#include <thread>

using namespace cv;
using namespace std;

 int lUserID_ =0;
//全局变量
 Mat g_BGRImage;
 LONG nPort = -1;
 ros::Publisher pub;
 bool whileFig=true;

/**
 * 海康摄像头ros驱动
 * 苏凯
 * 邮箱: 422168787@qq.com
 * 2023-03-27
 * rosrun haikangdecte haikangdecte_node
 */



 void CALLBACK DecCBFun(LONG nPort, char* pBuf, LONG nSize, FRAME_INFO* pFrameInfo, void* nReserved1, LONG nReserved2) {
     if (pFrameInfo->nType == T_YV12)
     {
         if (g_BGRImage.empty())
         {
             g_BGRImage.create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);
         }
         Mat YUVImage(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (unsigned char*)pBuf);
         cvtColor(YUVImage, g_BGRImage, COLOR_YUV2BGR_YV12);
         sensor_msgs::ImagePtr img_msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", g_BGRImage).toImageMsg();
         pub.publish(img_msg);
         YUVImage.~Mat();
     }
 }


 void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
 {

     switch (dwDataType)
     {
         case NET_DVR_SYSHEAD:
             if (!PlayM4_GetPort(&nPort))
             {
                 break;
             }
             //m_iPort = lPort;
             if (dwBufSize > 0)
             {
                 if (!PlayM4_SetStreamOpenMode(nPort, STREAME_REALTIME))
                 {
                     break;
                 }
                 if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 10 * 1024 * 1024))
                 {
                     break;
                 }
                 if (!PlayM4_Play(nPort, NULL))
                 {
                     break;
                 }
                 if (!PlayM4_SetDecCallBack(nPort, DecCBFun))
                 {
                     break;
                 }
             }
             break;
         case NET_DVR_STREAMDATA:
             if (dwBufSize > 0 && nPort != -1)
             {
                 if (!PlayM4_InputData(nPort, pBuffer, dwBufSize))
                 {
                     cout << "error" << PlayM4_GetLastError(nPort) << endl;

                     break;
                 }
             }
             break;
         default:
             if (dwBufSize > 0 && nPort != -1)
             {
                 if (!PlayM4_InputData(nPort, pBuffer, dwBufSize))
                 {

                     break;
                 }
             }
             break;
     }

 }


 bool callback(maindecte_srvs::maindecte::Request &request, maindecte_srvs::maindecte::Response &response) {

     std::cout << "entry function" << std::endl;
     int lRealPlayHandle;
     NET_DVR_PREVIEWINFO struPlay = {0};
     struPlay.hPlayWnd = NULL;
     struPlay.lChannel = 1;
     struPlay.dwStreamType = 0;
     struPlay.dwLinkMode = 0;
     struPlay.bBlocked = 0;
     lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID_, &struPlay, NULL, NULL);
     //*camera_RealPlay = lRealPlayHandle;

     if (lRealPlayHandle < 0)
     {
         printf("pyd---NET_DVR_RealPlay_V40 error, %d\n", NET_DVR_GetLastError());
     }
     else
     {
         std::cout << "NET_DVR_RealPlay_V40 success" << std::endl;
     }

     int msgtype =  request.msgtype;
     maindecte_msgs::Msgdata msgdata=  request.msgdata;

     int dwPTZCommand=  request.dwPTZCommand;//云台控制命令
     int dwStop=  request.dwStop;//0开始， 1停止
     int dwSpeed= request.dwSpeed;//速度 范围（1-7）

     std::string return_msg = "ok";
     std::cout << "MSG_type " << msgtype << std::endl;

     // NET_DVR_GET_FOCUSING_POSITION_STATE;
     switch (msgtype)
     {
         case 500001:  //云台控制
         {
             try
             {

                 std::cout << "云台控制 500001" << std::endl;
                 std::cout << "云台控制 0 开始 1停止:" << dwStop<<std::endl;
                 std::cout << "云台控制 0 dwPTZCommand" <<dwPTZCommand<< std::endl;
                 std::cout << "云台控制 0 开始 1停止" << std::endl;
                 if(dwPTZCommand<=0)
                     break;

                 int error1 = NET_DVR_PTZControl(lRealPlayHandle, dwPTZCommand, dwStop);
                 if (error1 < 0)
                 {
                     printf("pyd---500001云台控制  error, %d\n", NET_DVR_GetLastError());
                     //NET_DVR_Cleanup();

                 }

                 break;

             }
             catch (std::exception &e)
             {
                 std::cout << "exception : " << e.what() << std::endl;
             }
             break;
         }
         case 500002://带速度的云台控制
         {
             try
             {

                 std::cout << "云台控制 500002" << std::endl;
                 std::cout << "云台控制 0 开始 1停止:" << dwStop<<std::endl;
                 std::cout << "云台控制 0 dwPTZCommand" <<dwPTZCommand<< std::endl;

                 if(dwPTZCommand<=0)
                     break;

                 if(dwSpeed<=0)
                     dwSpeed=1;
                 if(dwSpeed>7)
                     dwSpeed=7;

                 int error1 = NET_DVR_PTZControlWithSpeed(lRealPlayHandle, dwPTZCommand, dwStop,dwSpeed);
                 if (error1 < 0)
                 {
                     printf("pyd---500001云台控制  error, %d\n", NET_DVR_GetLastError());
                     //NET_DVR_Cleanup();

                 }
                 break;
             }
             catch (std::exception &e)
             {
                 std::cout << "exception : " << e.what() << std::endl;
             }
             break;
         }
         default:
             break;
     }



     NET_DVR_StopRealPlay(lRealPlayHandle);
     response.result=return_msg;
     return true;
 }

 void signalHandler(int signum)
 {

     whileFig=false;
     ros::shutdown();
 }

//rosrun haikangdecte haikangdecte_node
 int main(int argc,char *argv[])
{

    //节点名
    string nodeName = "haikangdecte_node";
    //初始化节点
    ros::init(argc,argv,nodeName);
    //创建节点
    ros::NodeHandle nh_;
    ros::NodeHandle private_nh("~");
    signal(SIGINT, signalHandler);
    //创建Service Server
    const ros::ServiceServer &server = nh_.advertiseService("/maindecte_service", callback);
    pub = nh_.advertise<sensor_msgs::Image>("/hikrobot/camera/image", 1);

    ros::AsyncSpinner spinner(1); // Use 4 threads
    spinner.start();


    NET_DVR_Init();
    Demo_SDK_Version();
    NET_DVR_SetLogToFile(3, "./sdkLog");
    char cUserChoose = 'r';
    
    //Login device
    NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
    NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0};
    struLoginInfo.bUseAsynLogin = false;

    struLoginInfo.wPort = 8000;
    memcpy(struLoginInfo.sDeviceAddress, "10.9.162.175", NET_DVR_DEV_ADDRESS_MAX_LEN);//10.8.98.80
    memcpy(struLoginInfo.sUserName, "admin", NAME_LEN);//admin
    memcpy(struLoginInfo.sPassword, "Admin123", NAME_LEN);//hik12345

     lUserID_ = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);

    if (lUserID_ < 0)
    {
        printf("pyd---Login error, %d\n", NET_DVR_GetLastError());
        printf("Press any key to quit...\n");
        cin>>cUserChoose;

        NET_DVR_Cleanup();
        return HPR_ERROR;
    }


    NET_DVR_PREVIEWINFO struPlayInfo = { 0 };
    struPlayInfo.hPlayWnd = NULL;         //需要SDK解码时句柄设为有效值，仅取流不解码时可设为空
    struPlayInfo.lChannel = 1;           //预览通道号
    struPlayInfo.dwStreamType = 1;       //0-主码流，1-子码流，2-码流3，3-码流4，以此类推
    struPlayInfo.dwLinkMode = 0;         //0- TCP方式，1- UDP方式，2- 多播方式，3- RTP方式，4-RTP/RTSP，5-RSTP/HTTP
    struPlayInfo.bBlocked = 0; //0- 非阻塞取流， 1- 阻塞取流
    LONG   lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID_, &struPlayInfo, fRealDataCallBack, NULL);
    if (lRealPlayHandle < 0)
    {
        printf("NET_DVR_RealPlay_V40 error\n");
        printf("%d\n", NET_DVR_GetLastError());
        NET_DVR_Logout(lUserID_);
        NET_DVR_Cleanup();
        return 1;
    }

    while (ros::ok()&&whileFig)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

   /**
    while ('q' != cUserChoose)
    {
        printf("\n");
        printf("Input 1, Test GetStream\n");
        printf("      2, Test Configure params\n");
        printf("      3, Test Alarm\n");
        printf("      4, Test Capture Picture\n");
        printf("      5, Test play back\n");
        printf("      6, Test Voice\n");
        printf("      7, Test SDK ability\n");
        printf("      8, Test tool interface\n");

        printf("      7, Test Matrix decode\n");
        printf("      8, Test PTZ\n");
        printf("      9, Test Format\n");
        printf("      0, Test Update\n");
        printf("      a, Test Serial trans\n");
        printf("      b, Test Configure Params\n");
        printf("      c, Test VCA && IVMS\n");

        printf("      q, Quit.\n");
        printf("Input:");

        cin>>cUserChoose;
        switch (cUserChoose)
        {
        case '1':
            Demo_GetStream_V30(lUserID_); //Get stream.
            break;
        case '2':
            Demo_ConfigParams(lUserID_);  //Setting params.
            break;
        case '3':
            Demo_Alarm();         //Alarm & listen.
            break;
        case '4':
            Demo_Capture();
            break;
        case '5':
            Demo_PlayBack((int)lUserID_);     //record & playback
            break;
        case '6':
            Demo_Voice();
            break;
        case '7':
            Demo_SDK_Ability();
            break;
		case '8':
			Demo_DVRIPByResolveSvr();
			break;
        default:
            break;
        }
    }
     */

    // 停止预览
    NET_DVR_StopRealPlay(lRealPlayHandle);
    // 注销登录
    NET_DVR_Logout(lUserID_);
    //logout
    NET_DVR_Logout_V30(lUserID_);
    // 释放SDK资源
    NET_DVR_Cleanup();
    return 0;
}

#endif
